package com.zhuchang.self_rpc.test.democoding.nettydemo;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.GenericFutureListener;

/**
 * @Author RenPu
 * @Date 2022/2/9 9:36
 * @Version 1.0
 * @Description: 编写NettyServer的编码
 **/
public class NettyServer {

    public static void main(String[] args) throws InterruptedException {

        //创建bossGroup线程组(
        // 1：负责通过选择器，获取可以处理的事件（socketChannel），
        // 2：将socketChannel投放到队列里，再从队列里获取socketChannel封装为NioSocketChannel,
        // 3：NioSocketChannel注册到workGroup中的selector(便于工作线程组获取NioSocketChannel，获取对应的数据信息进行业务处理))，
        // 创建workGroup线程组(
        //1: 监听selector中可处理的事件
        //2：获取Channel中的数据信息根据对应的业务逻辑处理
        //3：处理结果的封装以及相应

        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();

        //创建服务端启动对象
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workGroup)            //服务端对象设定配置线程组
                    .channel(NioServerSocketChannel.class)  //服务端设置Channel类型
                    .option(ChannelOption.SO_BACKLOG, 128) //服务端设置线程队列个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true)//设置保持活动连接状态
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        //创建一个通道初始化对象(匿名对象)
                        //给pipeline 设置处理器
                        @Override
                        protected void initChannel(SocketChannel sc) throws Exception {
                            //可以使用一个集合管理 SocketChannel，
                            // 推送消息时，可以将业务加入到各个channel 对应的 NIOEventLoop 的 taskQueue 或者 scheduleTaskQueue
                            System.out.println("客户端socketchannel hashcode=" + sc.hashCode());
                            sc.pipeline().addLast(new NettyServerHandler()); //根据责任链模式，便于扩展添加自定义的处理逻辑
                        }
                    }); // 给我们的workerGroup 的 EventLoop 对应的管道设置处理器

            System.out.println(".......服务器 is ready .....");


            //服务端启动对象绑定端口并同步启动，获取返回值进行校验服务是否正确启动
            ChannelFuture channelFuture = bootstrap.bind(8688).sync();
            channelFuture.addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isSuccess()) {
                        System.out.println("服务端启动成功..........");
                    } else {
                        System.out.println("服务端启动失败请重新检查异常，并做出对应的修复.......");
                    }
                }
            });


            //对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();

        }


    }




}
